home *** CD-ROM | disk | FTP | other *** search
/ 10,000 Great Games / 10,000 Great Games.iso / Product / 66 / data1.cab / Source_Files / Src / Bitmap.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  6KB  |  323 lines

  1. #include "stdafx.h"
  2.  
  3. cBMP *bitmaps = 0;
  4.  
  5. cBMP::cBMP(int _w, int _h, char *_name)
  6. {
  7.     // Set variables
  8.  
  9.     w = _w;
  10.     h = _h;
  11.     usedcount = 0;
  12.     dds_vid = 0;
  13.  
  14.     // Set name
  15.  
  16.     name = strdup(_name);
  17.  
  18.     // Create surface
  19.  
  20.     if ((dds = create_surface(w, h, DDSCAPS_SYSTEMMEMORY, DDSD_CKSRCBLT)) == 0)
  21.         error("Unable to create surface for %s", name);
  22.  
  23.     // Add image to list
  24.  
  25.     add((cList **)&bitmaps);
  26. }
  27.  
  28. cBMP::~cBMP()
  29. {
  30.     free(name);
  31.     safe_release(&dds);
  32.     safe_release(&dds_vid);
  33. }
  34.  
  35. void cBMP::reset()
  36. {
  37.     for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
  38.     {
  39.         safe_release(&b->dds_vid);
  40.         b->usedcount = 0;
  41.     }
  42. }
  43.  
  44. LPDIRECTDRAWSURFACE4 cBMP::bestptr(cSurface *dest)
  45. {
  46.     // If we don't have the caps don't bother putting things in video memory
  47.     
  48.     if (no_blit_hardware || !hardware_blit_caps || (dest->caps.dwCaps & DDSCAPS_SYSTEMMEMORY))
  49.         return dds;
  50.     
  51.     // Increase usedcount
  52.  
  53.     usedcount++;
  54.  
  55.     // Resort, least used images first
  56.  
  57.     sort(&this_minus_other_usedcount);
  58.  
  59.     // Return pointer
  60.     
  61.     return dds_vid != 0? dds_vid:dds;
  62. }
  63.  
  64. int cBMP::this_minus_other_usedcount(cList *t, cList *o)
  65. {
  66.     return ((cBMP *)t)->usedcount - ((cBMP *)o)->usedcount;
  67. }
  68.  
  69. void cBMP::make_dynamic_use_of_video_mem()
  70. {
  71.     // If we don't have the right blit caps then don't bother putting things in video memory
  72.     
  73.     if (no_blit_hardware || !hardware_blit_caps)
  74.         return;
  75.  
  76.     // Get end of list
  77.     
  78.     cBMP *e = (cBMP *)cList::get_end((cList *)bitmaps);
  79.     
  80.     // No images or none ever used
  81.     
  82.     if (e == 0 || e->usedcount <= 0)
  83.         return;
  84.     
  85.     // Try to find an image that could be blit to video memory
  86.     
  87.     for (; e != bitmaps && e->dds_vid != 0; e = (cBMP *)e->prev);
  88.     
  89.     // All images are in video memory or no more used images, good!
  90.     
  91.     if (e == bitmaps || e->usedcount <= 0)
  92.         return;
  93.     
  94.     // Allocate image
  95.     
  96.     e->dds_vid = create_surface(e->w, e->h, DDSCAPS_VIDEOMEMORY, DDSD_CKSRCBLT);
  97.     
  98.     if (e->dds_vid != 0)
  99.     {
  100.         // Image created, now blit the contents to video memory
  101.         
  102.         while (FAILED(e->dds_vid->BltFast(0, 0, e->dds, 0, DDBLTFAST_WAIT)))
  103.             if (FAILED(e->dds->Restore()) || FAILED(e->dds_vid->Restore()))
  104.             {
  105.                 // Some resource permanently lost
  106.  
  107.                 safe_release(&e->dds_vid);
  108.                 
  109.                 // Exit loop
  110.                 
  111.                 break;
  112.             }
  113.             
  114.             return;            
  115.     }
  116.  
  117.     // Not enough room to allocate surface, search for least used image in video memory
  118.     
  119.     for (cBMP *b = bitmaps; b != e && b->dds_vid == 0; b = (cBMP *)b->next);
  120.     
  121.     // Is there one?
  122.     
  123.     if (b == e)
  124.     {
  125.         // No room for this image, make it very unimportant and resort it
  126.         
  127.         e->usedcount = -100;                        
  128.         e->relink((cList **)&bitmaps);
  129.         
  130.         return;
  131.     }
  132.     
  133.     // Release this image
  134.  
  135.     safe_release(&b->dds_vid);
  136. }            
  137.  
  138. static void create_add_file(const char *fn, const char *name)
  139. {
  140.     // Read the bitmap headers into memory
  141.  
  142.     CFile b;
  143.     
  144.     if (!b.Open(fn, CFile::modeRead | CFile::shareDenyWrite))
  145.         error("Unable to open %s", fn);
  146.  
  147.     BITMAPFILEHEADER bfh;
  148.     b.Read(&bfh, sizeof(bfh));
  149.  
  150.     BITMAPINFOHEADER bih;    
  151.     b.Read(&bih, sizeof(bih));
  152.  
  153.     // Check if it's in the right format
  154.  
  155.     if (bfh.bfType != 'MB')
  156.         error("Bitmap %s is not a bitmap", fn);
  157.  
  158.     if (bih.biHeight <= 0)
  159.         error("Bitmap %s is not bottom up", fn);
  160.     
  161.     if (bih.biBitCount != 8)
  162.         error("Bitmap %s is not 8 bit", fn);
  163.  
  164.     if (bih.biCompression != BI_RGB)
  165.         error("Bitmap %s is compressed!", fn);
  166.  
  167.     // Get width of scanline
  168.  
  169.     int w = (bih.biWidth + 3) & ~3;
  170.  
  171.     // Read bitmap data
  172.  
  173.     char *d = new char [bih.biHeight * w];
  174.     b.Seek(bfh.bfOffBits, CFile::begin);
  175.     b.Read(d, bih.biHeight * w);
  176.  
  177.     // Open database file 
  178.  
  179.     CFile f;
  180.     
  181.     if (!f.Open("Bitmaps.dat", CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareExclusive))
  182.         error("Unable to open Bitmaps.dat");
  183.  
  184.     f.SeekToEnd();
  185.  
  186.     // Write name of object + bytecount of string
  187.  
  188.     int l = strlen(name);        
  189.     f.Write(&l, sizeof(l));
  190.     f.Write(name, l);
  191.  
  192.     // Write bitmap width and height
  193.  
  194.     f.Write(&bih.biWidth, sizeof(bih.biWidth));
  195.     f.Write(&bih.biHeight, sizeof(bih.biHeight));
  196.  
  197.     // Write data
  198.  
  199.     for (int y = bih.biHeight - 1; y >= 0; y--)
  200.         f.Write(&d[w * y], bih.biWidth);
  201.  
  202.     // Release temporary space
  203.  
  204.     delete d;
  205. }
  206.  
  207. void cBMP::create_file()
  208. {
  209.     search_files("Bmp", "*.BMP", create_add_file);
  210. }
  211.  
  212. void cBMP::load()
  213. {    
  214.     BYTE *data, *d, *s;
  215.     int l, x, y, w, h;
  216.     char name[256];
  217.     CFile f;
  218.  
  219.     // Open bitmaps file
  220.  
  221.     if (!f.Open("Bitmaps.dat", CFile::modeRead | CFile::shareDenyWrite))
  222.         error("Unable to open Bitmaps.dat");
  223.     
  224.     while (f.Read(&l, sizeof(l)) == sizeof(l))
  225.     {
  226.         // Read name
  227.         
  228.         f.Read(name, l);
  229.         name[l] = 0;
  230.  
  231.         // Read dimensions    
  232.  
  233.         f.Read(&w, sizeof(w));
  234.         f.Read(&h, sizeof(h));
  235.  
  236.         // Read bitmap data
  237.  
  238.         data = new BYTE [w * h];
  239.         f.Read(data, w * h);
  240.  
  241.         // Create bitmap
  242.  
  243.         cBMP *b = new cBMP(w, h, name);
  244.     
  245.         // Lock the surface for writing bitmap data
  246.     
  247.         DDSURFACEDESC2 ddsd;
  248.         
  249.         ddsd.dwSize = sizeof(ddsd);
  250.     
  251.         if (FAILED(b->dds->Lock(0, &ddsd, DDLOCK_WAIT, 0)))
  252.             error("Unable to lock memory for bitmap load");
  253.     
  254.         // Copy data
  255.  
  256.         s = (BYTE *)ddsd.lpSurface;
  257.         d = data;
  258.  
  259.         switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
  260.         {
  261.         case 8:                    
  262.             for (y = 0; y < h; y++)
  263.             {
  264.                 for (x = 0; x < w; x++, s++, d++)
  265.                     *s = color_table_this_mode[*d];
  266.  
  267.                 s += ddsd.lPitch - w;
  268.             }
  269.             break;
  270.  
  271.         case 16:    
  272.             for (y = 0; y < h; y++)
  273.             {
  274.                 for (x = 0; x < w; x++, s += 2, d++)
  275.                     *(WORD *)s = color_table_this_mode[*d];
  276.  
  277.                 s += ddsd.lPitch - (w << 1);
  278.             }
  279.             break;
  280.  
  281.         case 24:    
  282.             for (y = 0; y < h; y++)
  283.             {
  284.                 for (x = 0; x < w; x++, s += 3, d++)
  285.                     *(WORD *)s = color_table_this_mode[*d],
  286.                     s[2] = color_table_this_mode[*d] >> 16;
  287.  
  288.                 s += ddsd.lPitch - (w << 1) - w;
  289.             }
  290.             break;
  291.  
  292.         case 32:
  293.             for (y = 0; y < h; y++)
  294.             {
  295.                 for (x = 0; x < w; x++, s += 4, d++)
  296.                     *(DWORD *)s = color_table_this_mode[*d];
  297.  
  298.                 s += ddsd.lPitch - (w << 2);
  299.             }
  300.             break;
  301.         }
  302.  
  303.         // Unlock memory
  304.  
  305.         b->dds->Unlock(0);
  306.  
  307.         // Release data
  308.  
  309.         delete data;
  310.     }
  311. }
  312.  
  313. cBMP *cBMP::get(char *fn)
  314. {
  315.     for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
  316.         if (eq(fn, b->name))
  317.             return b;
  318.  
  319.     error("Image %s not found", fn);
  320.  
  321.     return 0;
  322. }
  323.